package cn.sc.summer.mybatis.util;

import cn.sc.summer.constant.mybatisplus.TenantInfo;
import cn.sc.summer.exception.exceptions.CommonException;
import cn.sc.summer.mybatis.context.TenantContextHolder;
import org.springframework.stereotype.Component;

import java.util.concurrent.Callable;

/**
 * 类名：租户工具类
 *
 * @author a-xin
 * @date 2024/6/29 18:57
 */
@Component
public class TenantUtil {

    /**
     * 指定租户ID执行
     *
     * @param tenantId 租户ID
     * @param runnable 执行方法
     */
    public static void run(String tenantId, Runnable runnable) {
        TenantInfo oldTenantInfo = TenantContextHolder.getTenantInfo();
        try {
            TenantInfo newTenantInfo = new TenantInfo();
            newTenantInfo.setTenantId(tenantId);
            newTenantInfo.setIgnoreTenant(Boolean.FALSE);
            TenantContextHolder.setTenantInfo(newTenantInfo);
            runnable.run();
        } catch (Exception e) {
            throw new CommonException(e.getMessage());
        } finally {
            TenantContextHolder.setTenantInfo(oldTenantInfo);
        }
    }

    /**
     * 指定租户ID执行，有返回值
     *
     * @param tenantId 租户ID
     * @param callable 执行方法
     * @param <V>      返回结果类型
     * @return 执行结果
     */
    public static <V> V run(String tenantId, Callable<V> callable) {
        TenantInfo oldTenantInfo = TenantContextHolder.getTenantInfo();
        try {
            TenantInfo newTenantInfo = new TenantInfo();
            newTenantInfo.setTenantId(tenantId);
            newTenantInfo.setIgnoreTenant(Boolean.FALSE);
            TenantContextHolder.setTenantInfo(newTenantInfo);
            return callable.call();
        } catch (Exception e) {
            throw new CommonException(e.getMessage());
        } finally {
            TenantContextHolder.setTenantInfo(oldTenantInfo);
        }
    }

    /**
     * 忽略租户ID执行
     *
     * @param runnable 执行方法
     */
    public static void ignore(Runnable runnable) {
        TenantInfo oldTenantInfo = TenantContextHolder.getTenantInfo();
        try {
            TenantInfo newTenantInfo = new TenantInfo();
            newTenantInfo.setIgnoreTenant(Boolean.TRUE);
            TenantContextHolder.setTenantInfo(newTenantInfo);
            runnable.run();
        } catch (Exception e) {
            throw new CommonException(e.getMessage());
        } finally {
            TenantContextHolder.setTenantInfo(oldTenantInfo);
        }
    }

    /**
     * 忽略租户执行，有返回值
     *
     * @param callable 执行方法
     * @param <V>      返回值类型
     * @return 执行结果
     */
    public static <V> V ignore(Callable<V> callable) {
        TenantInfo oldTenantInfo = TenantContextHolder.getTenantInfo();
        try {
            TenantInfo newTenantInfo = new TenantInfo();
            newTenantInfo.setIgnoreTenant(Boolean.TRUE);
            TenantContextHolder.setTenantInfo(newTenantInfo);
            return callable.call();
        } catch (Exception e) {
            throw new CommonException(e.getMessage());
        } finally {
            TenantContextHolder.setTenantInfo(oldTenantInfo);
        }
    }

}
